package mac5855.app.dao;

import java.io.IOException;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import mac5855.app.lucene.search.SearchEngine;
import mac5855.app.models.Categoria;
import mac5855.app.models.GerenciadorDePerguntas;
import mac5855.app.models.Pergunta;
import mac5855.app.models.Resposta;
import mac5855.app.models.Usuario;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.Hit;
import org.apache.lucene.search.Hits;

public class JdbcPerguntaDAO implements PerguntaDAO {

	@Override
	public void create(Pergunta newInstance) {
		Connection conn = null;
		conn = JdbcDAOFactory.createConnection();
		try {
			PreparedStatement stmt = conn
			.prepareStatement("insert into perguntas (titulo, data, usuario_id, categoria_id) values (?,?,?,?)");

			stmt.setString(1, newInstance.getTitulo());
			Date data = new Date(newInstance.getData().getTime());
			stmt.setDate(2, data);
			stmt.setString(3, newInstance.getUsuario().getEmail());
			stmt.setInt(4, newInstance.getCategoria().getId());

			stmt.execute();

			stmt.close();

			stmt = conn
			.prepareStatement("select * from perguntas where titulo = ? and usuario_id  =? and categoria_id = ? and data = ?");
			stmt.setString(1, newInstance.getTitulo());
			stmt.setString(2, newInstance.getUsuario().getEmail());
			stmt.setInt(3, newInstance.getCategoria().getId());
			stmt.setDate(4, data);

			ResultSet rs = stmt.executeQuery();

			if (rs.next()) {
				// criando o objeto Contato
				Pergunta pergunta = new Pergunta();
				pergunta.setId(rs.getInt("id"));
				pergunta.setTitulo(rs.getString("titulo"));
				pergunta.setData(rs.getDate("data"));
				pergunta.setVotoPositivo(rs.getInt("voto_positivo"));
				pergunta.setVotoNegativo(rs.getInt("voto_negativo"));

				Categoria categoria = new Categoria();
				categoria.setId(rs.getInt("categoria_id"));

				CategoriaDAO categoriaDAO = DAOFactory.getDAOFactory(1).getCategoriaDAO();
				categoria = categoriaDAO.find(categoria);
				pergunta.setCategoria(categoria);

				UsuarioDAO usuarioDAO = DAOFactory.getDAOFactory(1).getUsuarioDAO();
				Usuario usuario = usuarioDAO.findByEmail(rs.getString("usuario_id"));
				pergunta.setUsuario(usuario);
				GerenciadorDePerguntas.getInstancia().adicionaPergunta(pergunta);
			}
			rs.close();
			stmt.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Gravado!");
		JdbcDAOFactory.releaseConnection(conn);

	}

	@Override
	public void delete(Integer id) {
		Connection conn = null;
		conn = JdbcDAOFactory.createConnection();
		try {
			PreparedStatement stmt = conn.prepareStatement("delete from perguntas where id = ?");

			stmt.setInt(1, id);
			stmt.execute();

			stmt.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Gravado!");
		JdbcDAOFactory.releaseConnection(conn);
	}

	@Override
	public Pergunta find(Pergunta object) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Pergunta[] findAll() {
		Connection conn = JdbcDAOFactory.createConnection();
		List<Pergunta> perguntas = new ArrayList<Pergunta>();
		try {
			PreparedStatement stmt = conn.prepareStatement("select * from perguntas");
			ResultSet rs = stmt.executeQuery();

			while (rs.next()) {
				// criando o objeto Contato
				Pergunta pergunta = new Pergunta();
				pergunta.setId(rs.getInt("id"));
				pergunta.setTitulo(rs.getString("titulo"));
				pergunta.setData(rs.getDate("data"));
				pergunta.setVotoPositivo(rs.getInt("voto_positivo"));
				pergunta.setVotoNegativo(rs.getInt("voto_negativo"));

				Categoria categoria = new Categoria();
				categoria.setId(rs.getInt("categoria_id"));

				CategoriaDAO categoriaDAO = DAOFactory.getDAOFactory(1).getCategoriaDAO();
				categoria = categoriaDAO.find(categoria);
				pergunta.setCategoria(categoria);

				RespostaDAO respostaDAO = DAOFactory.getDAOFactory(1).getRespostaDAO();
				Resposta[] respostas = respostaDAO.findByPergunta(pergunta);

				pergunta.setRespostas(respostas);

				UsuarioDAO usuarioDAO = DAOFactory.getDAOFactory(1).getUsuarioDAO();
				Usuario usuario = usuarioDAO.findByEmail(rs.getString("usuario_id"));
				pergunta.setUsuario(usuario);

				// adicionando o objeto à lista
				perguntas.add(pergunta);
			}

			rs.close();
			stmt.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		JdbcDAOFactory.releaseConnection(conn);

		return perguntas.toArray(new Pergunta[perguntas.size()]);
	}

	@Override
	public void update(Pergunta transientObject) {
		// TODO Auto-generated method stub

	}

	@Override
	public Pergunta findById(Integer id) {
		Connection conn = JdbcDAOFactory.createConnection();
		Pergunta pergunta = null;
		try {
			PreparedStatement stmt = conn.prepareStatement("select * from perguntas where id = ?");
			stmt.setInt(1, id);
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) { // Query only returns 1 record in the result set;
				// only 1
				pergunta = new Pergunta();
				pergunta.setId(rs.getInt("id"));
				pergunta.setTitulo(rs.getString("titulo"));
				pergunta.setData(rs.getDate("data"));
				pergunta.setVotoPositivo(rs.getInt("voto_positivo"));
				pergunta.setVotoNegativo(rs.getInt("voto_negativo"));
				Categoria categoria = new Categoria();
				categoria.setId(rs.getInt("categoria_id"));

				CategoriaDAO categoriaDAO = DAOFactory.getDAOFactory(1).getCategoriaDAO();
				categoria = categoriaDAO.find(categoria);
				pergunta.setCategoria(categoria);

				UsuarioDAO usuarioDAO = DAOFactory.getDAOFactory(1).getUsuarioDAO();
				Usuario usuario = usuarioDAO.findByEmail(rs.getString("usuario_id"));
				pergunta.setUsuario(usuario);

			}
			rs.close();
			stmt.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		JdbcDAOFactory.releaseConnection(conn);

		return pergunta;
	}

	@Override
	public Pergunta[] findAllByTituloAndCategoria(String titulo, Integer categoria_id) {
		List<Pergunta> perguntas = new ArrayList<Pergunta>();
		try {
			SearchEngine searchEngine = new SearchEngine();

			Hits hits = searchEngine.performSearch(titulo);

			Iterator<Hit> iter = hits.iterator();
			while (iter.hasNext()) {
				Hit hit = iter.next();
				Document doc = hit.getDocument();

				perguntas.add(findById(Integer.parseInt(doc.get("id"))));
			}

		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return perguntas.toArray(new Pergunta[perguntas.size()]);
	}

	@Override
	public Pergunta[] findByCategoriaId(int id) {
		Connection conn = JdbcDAOFactory.createConnection();
		List<Pergunta> perguntas = new ArrayList<Pergunta>();
		try {
			PreparedStatement stmt = conn.prepareStatement("select * from perguntas where categoria_id = ?");
			stmt.setInt(1, id);
			ResultSet rs = stmt.executeQuery();

			while (rs.next()) {
				// criando o objeto Contato
				Pergunta pergunta = new Pergunta();
				pergunta.setId(rs.getInt("id"));
				pergunta.setTitulo(rs.getString("titulo"));
				pergunta.setData(rs.getDate("data"));
				pergunta.setVotoPositivo(rs.getInt("voto_positivo"));
				pergunta.setVotoNegativo(rs.getInt("voto_negativo"));

				Categoria categoria = new Categoria();
				categoria.setId(rs.getInt("categoria_id"));

				CategoriaDAO categoriaDAO = DAOFactory.getDAOFactory(1).getCategoriaDAO();
				categoria = categoriaDAO.find(categoria);
				pergunta.setCategoria(categoria);

				UsuarioDAO usuarioDAO = DAOFactory.getDAOFactory(1).getUsuarioDAO();
				Usuario usuario = usuarioDAO.findByEmail(rs.getString("usuario_id"));
				pergunta.setUsuario(usuario);

				// adicionando o objeto à lista
				perguntas.add(pergunta);
			}

			rs.close();
			stmt.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		JdbcDAOFactory.releaseConnection(conn);

		return perguntas.toArray(new Pergunta[perguntas.size()]);
	}

	@Override
	public void vote(int id, boolean voteThrough) {

		Connection conn = JdbcDAOFactory.createConnection();

		String column = (voteThrough) ? "voto_positivo" : "voto_negativo";

		try {
			PreparedStatement stmt = conn.prepareStatement("select " + column + " from perguntas where id = ?");
			stmt.setInt(1, id);
			ResultSet rs = stmt.executeQuery();

			if (rs.next()) {
				int pontos = rs.getInt(1);
				rs.close();
				stmt.close();
				stmt = conn.prepareStatement("update perguntas set " + column + " = ? where id = ?");
				stmt.setInt(1, pontos + 1);
				stmt.setInt(2, id);
				stmt.executeUpdate();
				stmt.close();
			}

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		JdbcDAOFactory.releaseConnection(conn);

	}

	@Override
	public void addFavorite(int id, String userEmail) {

		Connection conn = null;
		conn = JdbcDAOFactory.createConnection();
		try {
			PreparedStatement stmt = conn
			.prepareStatement("insert into favoritos (pergunta_id, usuario_id) values (?,?)");

			stmt.setInt(1, id);
			stmt.setString(2, userEmail);

			stmt.execute();

			stmt.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Gravado!");
		JdbcDAOFactory.releaseConnection(conn);

	}

	@Override
	public boolean isFavorite(int id, String userEmail) {

		Connection conn = JdbcDAOFactory.createConnection();

		boolean isFav = false;
		try {
			PreparedStatement stmt = conn
			.prepareStatement("select * from favoritos where usuario_id = ? and pergunta_id = ?");
			stmt.setString(1, userEmail);
			stmt.setInt(2, id);
			System.out.println(stmt.toString());
			ResultSet rs = stmt.executeQuery();
			if (rs.next()) { // Query only returns 1 record in the result set;
				// only 1
				isFav = true;

			}

			rs.close();
			stmt.close();

		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		JdbcDAOFactory.releaseConnection(conn);

		return isFav;
	}

}
